package org.aspire.game;

import org.aspire.core.sys.GSystem;
import org.aspire.data.Updateable;
import org.aspire.graphics.Frame;
import org.aspire.graphics.Strip;

/******************************************************************************
 * An animation manages a strip of frames and the amount of time to display
 * each frame to produce an effect similar to motion pictures.
 * 
 * @author JPACarabuena
 *****************************************************************************/
public class Animation implements Updateable {

	// ========================================================================
	// Constants
	// ========================================================================

	// ========================================================================
	// Static Methods
	// ========================================================================

	// ========================================================================
	// Fields
	// ========================================================================

	/**************************************************************************
	 * The strip of frames to be used in this animation.
	 *************************************************************************/
	private Strip strip;
	
	/**************************************************************************
	 * The index of the current frame.
	 *************************************************************************/
	private int currentFrameIndex;
	
	private Timer animationTimer;
	
	private int startFrame;
	
	private int finishFrame;
	
	// ========================================================================
	// Constructors
	// ========================================================================
	
	public Animation(Strip strip, long frameTime) {
		this.strip = strip;
		this.animationTimer = new Timer(frameTime);
		this.startFrame = 0;
		this.finishFrame = this.strip.count() - 1;
		this.start();
	}
	
	/**************************************************************************
	 * Construct a new animation with the specified strip of frames with the
	 * default duration at 100 milliseconds per frame.
	 * 
	 * @param strip	the strip of frames.
	 *************************************************************************/
	public Animation(Strip strip) {
		this(strip, 100);
	}
	
	// ========================================================================
	// Getters & Setters
	// ========================================================================

	/**************************************************************************
	 * Returns the strip of frames used in this animation.
	 * 
	 * @return	the strip of frames.
	 *************************************************************************/
	public Strip getStrip() {
		return this.strip;
	}
	
	/**************************************************************************
	 * Sets the strip of frames to be used in this animation to the specified
	 * strip.
	 * 
	 * @param strip the new strip of frames.
	 *************************************************************************/
	public void setStrip(Strip strip) {
		this.strip = strip;
	}
	
	// ========================================================================
	// Override Methods
	// ========================================================================

	@Override
	public void update(long elapsedTime) {
		GSystem.println("Current Frame: " + this.currentFrameIndex);
		GSystem.println("Current Time: " + this.animationTimer.getCurrentTick());
		if(this.animationTimer.action(elapsedTime)) {
			if(++this.currentFrameIndex > this.finishFrame) {
				this.currentFrameIndex = this.startFrame;
			}
		}
	}
	
	// ========================================================================
	// Methods
	// ========================================================================

	/**************************************************************************
	 * Refresh the animation back to its initial state.
	 *************************************************************************/
	public void start() {
		this.animationTimer.refresh();
	}
	
	/**************************************************************************
	 * Returns the current frame of the animation strip.
	 * 
	 * @return the current frame.
	 *************************************************************************/
	public Frame getFrame() {
		return this.strip.getFrameAt(this.currentFrameIndex);
	}
	
	// ========================================================================
	// Inner & Anonymous Classes
	// ========================================================================
	
}